'''
MongoDB是10gen公司开发的一款以高性能和可扩展性为特征的开源软件。它是一个介于关系数据库和非关系数据库之间的产品，是非关系数据库当中功能最丰富，最像关系数据库的，MongoDB最大的特点是它支持的查询语言非常强大，其语法有点类似于面向对象的查询语言，几乎可以实现类似关系数据库单表查询的绝大部分功能，而且还支持对数据建立索引。它是一个面向集合的，模式自由的文档型数据库。
所谓“面向集合”（Collection-Oriented），意思是数据被分组存储在数据集中，被称为一个集合（Collection)。每个集合在数据库中都有一个唯一的标识名，并且可以包含无限数目的文档。集合的概念类似关系型数据库（RDBMS）里的表（table），不同的是它不需要定义任何模式（schema)。Nytro MegaRAID技术中的闪存高速缓存算法，能够快速识别数据库内大数据集中的热数据，提供一致的性能改进。
模式自由（schema-free)，意味着对于存储在Mongodb数据库中的文件，我们不需要知道它的任何结构定义。如果需要的话，你完全可以把不同结构的文件存储在同一个数据库里。
存储在集合中的文档，被存储为键-值对的形式。键用于唯一标识一个文档，为字符串类型，而值则可以是各种复杂的文件类型。我们称这种存储形式为BSON（Binary Serialized Document Format）。

MongoDB的主要特点：
(1)MongoDB提供了一个面向文档存储，操作起来比较简单和容易的非关系型数据库。
(2)你可以在MongoDB记录中设置任何属性的索引来实现更快的排序。
(3)你可以通过本地或者网络创建数据镜像，这使得MongoDB含有更强的扩展性。
(4)如果负载增加(需要更多的存储空间和更强的处理能力)，它可以分布在计算机网络中的其它节点上，这就是所谓的分片。
(5)MongoDB支持丰富的查询表达式，查询指令使用json形式的标记，可轻易查询文档中内嵌的对象和数组。
(6)MongoDB使用update()命令可以实现替换文档(数据)或者一些指定的数据字段。
(7)MongoDB中的Map/Reduce主要是用来对数据进行批量处理和聚合操作，Map函数调用emit(key,value)遍历集合中所有的记录，将key与value传递给Reduce函数进行处理。另外Map函数和Reduce函数是使用JavaScript编写的，所以可以通过db.runCommand和mapreduce命令来执行MapReduce操作。
(8)GridFS是MongoDB中的一个内置功能，可以用于存放大量小文件。
(9)MongoDB允许在服务端执行脚本，可以用JavaScript编写某个函数，直接在服务端执行，也可以把函数的定义存储在服务端，下次直接调用即可。
(10)MongoDB支持各种编程语言：ruby、python、java、c++、php、c#等多种语言并且MongoDB的安装也非常简单。

面向文档的NoSQL数据库主要解决的问题不是高性能的并发读写，而是保证海量数据存储的同时，具有良好的查询性能。
MongoDB最大的特点是它支持的查询语言非常强大，其语法有点类似于面向对象的查询语言，
几乎可以实现类似关系数据库单表查询的绝大部分功能，而且还支持对数据建立索引。
由于MongoDB可以支持复杂的数据结构，而且带有强大的数据查询功能，
因此很多项目都考虑用MongoDB来代替MySQL等传统数据库来实现不是特别复杂的Web应用。
由于数据量实在太大，所以迁移到了MongoDB上面，数据查询的速度得到了非常显著的提升。

索引就是用来加速查询的。数据库索引与书籍的目录类似，有了目录就不需要翻遍整本书，
数据库则直接在索引中查找，使得查找速度能提高几个数量级，在索引中找到条目以后，就可以直接跳转到目标文档的位置。
MongoDB提供了多样性的索引支持，索引信息被保存在system.indexes中，且默认总是为_id创建索引，
它的索引使用方法基本和MySQL等关系型数据库一样，可以认为，索引是凌驾于数据存储系统的另一层系统，
所以各种结构迥异的存储都有相同或相似的索引实现及使用接口。

MongoDB的一大优点是，能够将数据库查询结果聚合成完全不同于原始集合的结构。
聚合指的是在MongoDB服务器中对文档执行一系列操作来生成结果集，
其效率比在应用程序中检索并处理文档高的多，因为大量的数据将由MongoDB服务器在本地处理。
MongoDB聚合框架相当杰出，简化了大量操作来处理数据，并提供了一组强大、针对数据集合进行检查和计算的聚合操作。

管道：管道在Unix和Linux中，一般用于将当前命令的输出结果作为下一个命令的输入，
或把第二个命令的输出作为第三条命令的输入，以此类推，由两条以上的命令可形成一条管道。
MongoDB的聚合管道将文档在一个管道处理完毕后，把结果传递给下一个管道处理。管道操作是可以重复的。
表达式：处理输入文档并输出。表达式是无状态的，只能用于计算当前聚合管道的文档，不能处理其它的文档。

MapReduce是聚合工具中的最常用工具，使用MapReduce要实现两个函数，Map函数和Reduce函数，Map函数调用emit（key，value），
遍历collection中的所有记录，将key与value传递给Reduce函数进行处理。

MongoDB同关系型数据库一样，在数据量小时看不出任何问题，但是当数据的操作变的频繁，如对10万级的数据表连续进行查询操作，
MongDB会变的非常缓慢。针对这种情况，我们对MongoDB进行性能优化。

索引的机制是：当你往某各个集合插入多个文档后，每个文档在经过底层的存储引擎持久化后，会有一个位置信息，通过这个位置信息，
就能从存储引擎里读出该文档。比如mmapv1引擎里，位置信息是（文件id + 文件内offset），
在wiredtiger存储引擎里，位置信息是wiredtiger在存储文档时生成的一个key，通过这个key能访问到对应的文档。
对于索引的优化：MongoDB支持对DB的请求进行profiling，目前支持3种级别的profiling。生产环境建议使用1级别的profiling，
并根据自身需求配置合理的阈值，用于监测慢请求的情况，及时的做索引优化。

对于索引的优化，有两个建议：

（1）索引可以极大地提高查询性能，那么索引是不是越多越好？答案是否定的，索引并非越多越好，而是越少越好。每当你建立一个索引时，
系统会为你添加一个索引表，用于索引指定的列，然而当你对已建立索引的列进行插入或修改时，数据库则需要对原来的索引表进行重新排序，
重新排序的过程非常消耗性能，但应对少量的索引压力并不是很大，但如果索引的数量较多的话对于性能的影响可想而知。
所以在创建索引时需要谨慎建立索引，要把每个索引的功能都要发挥到极致，也就是说在可以满足索引需求的情况下，索引的数量越少越好。
（2）索引颗粒越少越好，在索引列中每个数据的重复数量称为颗粒，也叫作索引的基数。如果数据的颗粒过大，索引就无法发挥该有的性能。
例如，我们拥有一个"age"列索引，如果在"age"列中，20岁占了80%，如果现在要查询一个20岁，名叫"Tom"的人，我们则需要在表的80%的数据中查询，
索引的作用大大降低。所以，我们在建立索引时要尽量将数据颗粒小的列放在索引左侧，以保证索引发挥最大的作用。

优化器Profile
在Mysql中，优化数据库的依据是慢查询日志，在MongoDB中也提供类似的功能：MongoDB Database Profiler。
①开启Profiling功能
有两种方式可以控制Profiling的开关和级别，第一种是直接在启动参数里进行设置。启动MongoDB时加上-profile=级别即可，也可以在客户端调用
db.setProfilingLevel(级别)命令来实时配置，Profiler信息保存在system.profile中。
使用db.getProfilingLevel()命令可以获取当前的Profile级别。
Profile的级别可以取0、1和2三个值，它们分别表示的意义如下：
0：不开启
1：记录慢命令（默认为>100ms）
2：记录所有命令

优化性能方案
总结出以下七种优化方案：
优化方案1：创建索引
在查询条件的字段上，或排序条件的字段上创建索引，可以显著提高执行效率。
对于创建索引的建议是：如果很少读，那么尽量不要添加索引，因为索引越多，写操作会越慢。如果读量很大，才更适宜添加索引。
优化方案2：
使用limit()限定返回结果集的大小，可以减少database server的资源消耗，可以减少网络传输数据量。
优化方案3：
只查询使用到的字段，而不是查询所有字段。
优化方案4：
采用Capped Collection。Capped Collections比普通Collections的读写效率高。Capped Collections是高效率Collection类型，它有如下特点：
①固定大小：Capped Collections必须事先创建，并设置大小：db.createCollection('mycoll',{capped:true,size:100000})。
②Capped Collections可以insert和update操作：不能delete操作。只能用drop()方法删除整个Collection。
③默认基于Insert的次序排序的。如果查询时没有排序，则总是按照insert的顺序返回。
④FIFO。如果超过了Collection的限定大小，则用FIFO算法，新纪录将替代最先insert的记录。
优化方案5：
采用Server Side Code Execution。Server-Side Processing类似于SQL数据库的存储过程，使用Server-Side Processing可以减小网络通信的开销。
优化方案6：
强制索引hint。一般情况下MongoDB query optimizer都工作良好，但有些情况下使用hint()可以提高操作效率。
hint可以强制要求查询操作使用某个索引。
优化方案7：
采用Profiling。Profiling功能肯定是会影响效率的，但是不太严重，原因是它使用的是system.profile来记录，
而system.profile是一个Capped Collection，这种Collection在操作上有一些限制和特点，但是更效率更高。

Java驱动是MongoDB最早的驱动。它已经用于生产环境多年，而且非常稳定，是企业开发的首选。
要在Java应用中访问和使用MongoDB，需要使用Java MongoDB驱动程序。Java MongoDB驱动程序是一个库，它提供了多个对象，
供使用者连接数据库，进而查找和操作集合中的对象，这些对象分别表示MongoDB服务器连接、数据库、集合、游标和文档，
提供了在Java应用程序中集成MongoDB数据库中的数据所需的功能。
Java对象MongoClient提供了连接到MongoDB服务器和访问数据库的功能。要在应用程序中实现MongoDB，
首先要创建一个MongoClient对象实例，然后就可使用它来访问数据库。
'''
